package com.rankeiot.compiler;

import com.caoccao.javet.exceptions.JavetException;
import com.caoccao.javet.interop.V8Host;
import com.caoccao.javet.interop.V8Runtime;
import com.caoccao.javet.interop.executors.IV8Executor;
import com.caoccao.javet.values.primitive.V8ValueString;
import com.caoccao.javet.values.reference.V8Script;
import com.rankeiot.Utils;


import java.io.Closeable;
import java.io.IOException;

/**
 * 基于V8引擎的js编译器
 */
public class V8Compiler implements ICompiler, Closeable {
    private String compilerPath;
    private V8Host host;
    protected V8Runtime runtime;
    protected V8Script script;
    private String appendCode;
    public V8Compiler(String compilerPath, String appendCode){
        this.compilerPath=compilerPath;
        this.appendCode=appendCode;
        host=V8Host.getV8Instance();
        try {
            this.init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public V8Compiler(String compilerPath){
        this.compilerPath=compilerPath;

        host=V8Host.getV8Instance();
        try {
            this.init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    protected void doInit(V8Runtime runtime,StringBuilder code) throws JavetException {

    }
    private void init() throws JavetException {
       runtime=host.createV8Runtime();
        StringBuilder sb=new StringBuilder();
        sb.append("function atob(src){ return Buffer.from(src,'base64').toString();};");
        sb.append("function btoa(src){ return Buffer.from(src).toString('base64');};");
        sb.append("let window={document:{getElementsByTagName:function(){return {length:0};}}};");
        sb.append(Utils.loadText(compilerPath));
        if(appendCode!=null){
            sb.append(appendCode);
        }
        doInit(runtime,sb);
        IV8Executor executor= runtime.getExecutor(sb.toString());
        script = executor.compileV8Script();
        script.execute(false);
    }

    @Override
    public String compile(String source) {
        try {
            V8ValueString obj = runtime.getGlobalObject().invoke("compile",source);
            return obj.getValue();
        } catch (JavetException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public void close() throws IOException {
        try {
            if(!script.isClosed()){
                script.close(true);
            }
        } catch (JavetException e) {
            e.printStackTrace();
        }
        try {
            if(!runtime.isClosed()) {
                runtime.resetContext();
                runtime.resetIsolate();
                runtime.close(true);
            }
        } catch (JavetException e) {
            e.printStackTrace();
        }

    }
}
